package com.maimao.kill.service;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.maimao.core.constant.KillConstant;
import com.maimao.core.exception.MaiMaoDaoException;
import com.maimao.core.exception.MaiMaoKillException;
import com.maimao.kill.controller.KillController;
import com.maimao.kill.mapper.KillGoodsMapper;
import com.maimao.model.kill.KillGoods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.maimao.core.constant.KillConstant.DEFAULT_KILL_CIRCLE;

/**
 * @author MaoLin Wang
 * @date 2021/4/13 4:40 下午
 */
@Service
@Slf4j
public class KillGoodsService {

    public static final int DEFAULT_TIMEOUT = 5;


    @Autowired
    private Cache<Long, KillGoods> killDetailCache;

    @Autowired
    private KillGoodsMapper killGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 根据id查询秒杀商品信息
     *
     * @param killId
     * @return
     */
    public KillGoods details(Long killId) {
        String key = KillConstant.KILL_GOODS_DETAIL + killId;

        //先从本地缓存取
        KillGoods killGoodsCache = killDetailCache.getIfPresent(killId);
        if (null != killGoodsCache) {
            log.info("get killGoods from caffeine cache....killId:{}", killId);
            return killGoodsCache;
        }
        //再从redis取
        Object killGoods = redisTemplate.opsForValue().get(key);
        if (null != killGoods) {
            log.info("get killGoods from redis....killId:{}", killId);
            killGoodsCache = (KillGoods) killGoods;
            killDetailCache.put(killId, killGoodsCache);
            return killGoodsCache;
        }
        //最后打到数据库
        synchronized (killGoodsMapper) {
            killGoodsCache = killDetailCache.getIfPresent(killId);
            if (null != killGoodsCache) {
                log.info("get killGoods from caffeine cache....killId:{}", killId);
                return killGoodsCache;
            }
            killGoods = redisTemplate.opsForValue().get(key);
            if (null != killGoods) {
                log.info("get killGoods from redis....killId:{}", killId);
                return JSONObject.parseObject(killGoods.toString(), KillGoods.class);
            }
            killGoodsCache = killGoodsMapper.selectById(killId);
            if (null != killGoodsCache) {
                killDetailCache.put(killId, killGoodsCache);
                redisTemplate.opsForValue().set(key, killGoodsCache, DEFAULT_KILL_CIRCLE, TimeUnit.HOURS);
                log.info("get killGoods from db....killId:{}", killId);
            } else {
                //防止缓存穿透
                redisTemplate.opsForValue().set(key, "null", DEFAULT_TIMEOUT, TimeUnit.MINUTES);
            }
        }
        return killGoodsCache;

    }

    /**
     * @param tomorrow true：预加载明日的数据 false：加载今日当前时间往后的数据
     */
    public List<KillGoods> selectAll(boolean tomorrow) {
       /* LocalDateTime now = LocalDateTime.now();
        LocalDateTime fromTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 0, 0, 0);

        LocalDateTime toTime = fromTime.plusDays(1);
        if (!tomorrow) {
            fromTime = now;
        }*/
        return killGoodsMapper.selectStockAll(null, null);
    }

    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime fromTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), 0, 0, 0);
        LocalDateTime toTime = fromTime.plusDays(1);
        System.out.println(fromTime);
        System.out.println(toTime);
    }

    /**
     * 扣减db库存
     * @param killId 秒杀id
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void reduceDbStock(Long killId) {
        int i = killGoodsMapper.reduceStock(killId);
        if (i <= 0) {
            throw new MaiMaoKillException("秒杀商品库存不足" + killId);
        }
    }
}


